<template>
	<div class="fx-virtual-input">
		<div
			tabindex="-1"
			class="fx-virtual-input__input"
			:style="{
				width: `${inputWidth}px`,
				color: isFocused ? '#333' : '#c6c6c6'
			}"
			@focus="onFocus"
			@blur="onBlur"
		>
			{{ currentVal }}
			<div v-show="isFocused" class="fx-virtual-input__cursor"></div>
		</div>
	</div>
</template>
<script lang="ts">
/**
 * VirtualInput by zz 2023/12/21
 * @desc input-number 输入框-数字类型
 * @param {value}  [String, Number] - 输入框值
 * @param {integer}  [Boolean] - 是否int
 * @param {disabled}  [Boolean] - 是否禁用
 * @param {min}  [String, Number] - 最小值
 * @param {max}  [String, Number] - 最大值
 * @param {pointSize}  [String, Number] - 小数位
 * @param {intLength}  [String, Number] - 整数位
 *
 *
 * @event {blur} 输入框失焦时触发
 * @event {focus} 输入框聚焦时触发
 */
import { getFxInstance } from '@/js/instance'
import { defineComponent, ref, watch, computed } from 'vue'
import utils from './utils'
import { fxEventBusKey } from '@/config/app_eventbus_config'
interface InputParams {
	key: string | null
	value: string
	type: string
}
export default defineComponent({
	name: 'virtualInput',
	props: {
		value: [String, Number],
		disabled: Boolean,
		readonly: Boolean,
		integer: Boolean,
		positive: Boolean,
		min: {
			type: Number,
			default: 0
		},
		max: {
			type: Number,
			default: Infinity
		},
		pointSize: {
			type: [String, Number],
			default: 4
		},
		intLength: {
			type: [String, Number],
			default: 8
		},
		inputWidth: {
			type: [String, Number],
			default: 100
		}
	},
	emits: ['update:value', 'change', 'focus', 'blur'],
	setup (props, { emit }) {
		const fxInstance = getFxInstance()
		const key = fxInstance.$fxUtils.createUUID()
		const currentVal = ref('')
		const intLength = typeof props.intLength === 'string' ? parseFloat(props.intLength) : props.intLength
		const computedNumberReg = computed(() => fxInstance.$fxUtils.regNumberIncludeNegative(props.pointSize))
		const format = (value:string|number|undefined):string|number => {
			value = String(value).replace(fxInstance.$fxUtils.regInputNumber(), '')
			return value === ''
				? 0 : props.integer
					? fxInstance.$fxUtils.floor(value) : props.pointSize
						? fxInstance.$fxUtils.toNumber(fxInstance.$fxUtils.toFixed(value, props.pointSize, false)) : fxInstance.$fxUtils.toNumber(value)
		}
		const range = (value:string|number) => {
			return Math.max(Math.min(props.max, format(value) as number), props.min)
		}
		watch(() => props.value, (value) => {
			if (!fxInstance.$fxUtils.isDef(value)) {
				currentVal.value = String('')
			} else {
				currentVal.value = String(value)
			}
		}, {
			immediate: true
		})
		const isFocused = ref(false)
		const setActiveInput = () => {
			isFocused.value = true
		}
		const setUnActiveInput = () => {
			isFocused.value = false
		}
		const onFocus = (event: Event) => {
			if (props.readonly || props.disabled) {
				event.preventDefault()
				return false
			}
			setActiveInput()
			utils.setFocusKey(key)
			emit('focus', event)
		}
		const onBlur = (event: Event) => {
			if (props.readonly || props.disabled) {
				event.preventDefault()
				return false
			}
			setUnActiveInput()
			cacheValue = ''
			cacheOperate = ''
			utils.setFocusKey('')
			emit('blur', event)
		}
		let cacheValue = ''
		let secondCacheValue = ''
		let cacheOperate = ''
		const operateActiveFlag = ref(false)
		const operateActive = () => {
			operateActiveFlag.value = true
		}
		const clearOperateActive = () => {
			operateActiveFlag.value = false
		}
		fxInstance.$fxEventBus.on(fxEventBusKey.VIRTUAL_INPUT_EMIT, (params: InputParams) => {
			if (params.key === key) {
				if (params.type === 'operate') {
					if (operateActiveFlag.value) {
						return false
					}
					if (cacheOperate !== '') {
						currentVal.value = `${range(`${Number(cacheValue) + Number(secondCacheValue)}`)}`
						const result = fxInstance.$fxUtils.toNumber(currentVal.value)
						emit('update:value', result)
						emit('change', result)
						secondCacheValue = ''
					}
					cacheValue = currentVal.value
					cacheOperate = params.value
					operateActive()
				} else if (params.type === 'number') {
					clearOperateActive()
					const testValue = `${currentVal.value}${params.value}`
					if (
						((testValue.includes('.')) && !computedNumberReg.value.test(testValue)) ||
						((testValue.includes('.')) && testValue.split('.')[0].replace(/-/g, '').length > intLength) ||
						((!testValue.includes('.')) && testValue.replace(/-/g, '').length > intLength)
					) {
						return false
					}
					if (cacheOperate === '') {
						currentVal.value += params.value
						const result = fxInstance.$fxUtils.toNumber(currentVal.value)
						emit('update:value', result)
						emit('change', result)
					} else {
						secondCacheValue = `${secondCacheValue}${params.value}`
						currentVal.value = secondCacheValue
					}
				} else if (params.type === 'acc') {
					clearOperateActive()
					if (cacheValue !== '' && cacheOperate !== '' && secondCacheValue !== '') {
						currentVal.value = `${range(`${Number(cacheValue) + Number(secondCacheValue)}`)}`
						cacheValue = ''
						secondCacheValue = ''
						cacheOperate = ''
						const result = fxInstance.$fxUtils.toNumber(currentVal.value)
						emit('update:value', result)
						emit('change', result)
					}
				} else if (params.type === 'decimal') {
					clearOperateActive()
					if (!currentVal.value.includes('.')) {
						if (!cacheOperate) {
							currentVal.value = `${currentVal.value}${params.value}`
						} else {
							secondCacheValue = `${currentVal.value}${params.value}`
							currentVal.value = secondCacheValue
						}
					}
				} else if (params.type === 'clear') {
					clearOperateActive()
					if (currentVal.value === '0') {
						return false
					}
					currentVal.value = '0'
					secondCacheValue = ''
					cacheValue = ''
					cacheOperate = ''
					const result = fxInstance.$fxUtils.toNumber(currentVal.value)
					emit('update:value', result)
					emit('change', result)
				} else if (params.type === 'back') {
					clearOperateActive()
					if (currentVal.value.length > 0 && currentVal.value !== '0') {
						if (currentVal.value.length === 1) {
							currentVal.value = '0'
							const result = fxInstance.$fxUtils.toNumber(currentVal.value)
							emit('update:value', result)
							emit('change', result)
							cacheOperate = ''
							cacheValue = currentVal.value
						} else {
							currentVal.value = currentVal.value.slice(0, -1)
							if (cacheOperate === '') {
								const result = fxInstance.$fxUtils.toNumber(currentVal.value)
								emit('update:value', result)
								emit('change', result)
							} else {
								cacheOperate = ''
								cacheValue = currentVal.value
							}
						}
					} else {
						return false
					}
				}
			}
		})
		return {
			isFocused,
			currentVal,
			onFocus,
			onBlur
		}
	}
})
</script>
<style lang="scss" scoped>
@import "$assets/stylus/varsty";
.fx-virtual-input {
	position: relative;
	.fx-virtual-input__input {
		float: right;
		overflow-x: auto;
		white-space: nowrap;
		.fx-virtual-input__cursor {
			position: absolute;
			top: 0;
			right: 1px;
			&::before{
				content: '';
			}
			&::after{
				content: '';
				border-right: 2px solid #000000;
				opacity: 1;
				animation: focus .7s forwards infinite;
				animation-delay: 100ms;
			}

			/* 闪烁动作 */
			@keyframes focus{
				from{
						opacity: 1;
				}to{
						opacity: 0;
				}
			}
		}
	}
}
</style>

